package cn.lxh.controller.remote;

import cn.hutool.core.date.DateUtil;
import cn.lxh.pojo.domain.*;
import cn.lxh.remote.api.RuleFeignApi;
import cn.lxh.remote.pojo.bo.CalculateMileageFeeBo;
import cn.lxh.remote.pojo.bo.DivideAccountsBo;
import cn.lxh.remote.pojo.result.DivideAccountsResult;
import cn.lxh.remote.pojo.result.MileageFeeResult;
import cn.lxh.remote.pojo.result.WaitFeeResult;
import cn.lxh.result.JSONResult;
import cn.lxh.service.*;
import cn.lxh.utils.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;


/**
 * RuleFeignApiImpl控制层
 */
@RestController
@Slf4j
public class RuleFeignApiImpl implements RuleFeignApi {

    @Autowired
    private IChargeRuleStartService chargeRuleStartService;

    @Autowired
    private IChargeRuleReturnService chargeRuleReturnService;

    @Autowired
    private IChargeRuleWaitService chargeRuleWaitService;

    @Autowired
    private IProfitsharingRuleBaseService profitsharingRuleBaseService;

    @Autowired
    private IProfitsharingRuleDeductCancelService profitsharingRuleDeductCancelService;

    @Autowired
    private IProfitsharingRuleDeductComplaintService profitsharingRuleDeductComplaintService;


    /**
     * 计算里程费用
     *
     * @param calculateMileageFeeBo
     * @return
     */
    @Override
    public JSONResult calculateMileageFee(CalculateMileageFeeBo calculateMileageFeeBo) {


        // 获取订单创建时间的小时数 (24小时制)
        int orderCreateHour = DateUtil.hour(calculateMileageFeeBo.getCreateTime(), true);

        // 根据订单创建时间获取里程费计价规则对象
        ChargeRuleStart chargeRuleStart = chargeRuleStartService.getOne(new LambdaQueryWrapper<ChargeRuleStart>()
                .ge(ChargeRuleStart::getHourEnd, orderCreateHour) // 计价规则结束小时大于等于orderCreateHour
                .le(ChargeRuleStart::getHourStart, orderCreateHour)); // 计价规则开始小时小于等于orderCreateHour

        // 判断里程费计价规则对象是否为空
        AssertUtil.isNotNull(chargeRuleStart, "里程费计价失败, 请稍后重试");

        // 创建里程费用返回参数
        MileageFeeResult mileageFeeResult = new MileageFeeResult();

        // 创建基础里程费 (起步价)
        BigDecimal mileageFee = chargeRuleStart.getAmount();
        // 基础里程费用 (起步价)
        mileageFeeResult.setBaseMileageAmount(mileageFee);

        // 获取里程数
        BigDecimal mileage = calculateMileageFeeBo.getMileage();
        // 返程里程数
        mileageFeeResult.setReturnMileage(mileage);

        // 获取基础里程数
        BigDecimal baseMileage = chargeRuleStart.getBaseMileage();
        // 基础里程
        mileageFeeResult.setBaseMileage(baseMileage);
        // 超出基础里程的里程数
        mileageFeeResult.setExceedBaseMileage(BigDecimal.ZERO);

        // 里程费
        mileageFeeResult.setMileageAmount(mileageFee);

        // 判断里程数是否在基础里程范围内, 如果不是, 那么超出的里程数按超出起步价每公里价格计价
        if (mileage.compareTo(baseMileage) > 0) { // 里程数大于基础里程数
            // 计算超出的里程数
            BigDecimal exceededMileage = mileage.subtract(baseMileage);
            log.info("exceededMileage超出的里程数 {}", exceededMileage);
            // 超出基础里程的里程数
            mileageFeeResult.setExceedBaseMileage(exceededMileage);

            // 计算超出的里程数的费用
            BigDecimal exceededMileageFee = exceededMileage.multiply(chargeRuleStart.getExceedEveryKmAmount());
            log.info("exceededMileageFee超出的里程数的费用 {}", exceededMileageFee);
            // 超出基础里程费用
            mileageFeeResult.setExceedBaseMileageAmount(exceededMileageFee);

            // 重新计算里程费
            mileageFee = mileageFee.add(exceededMileageFee);
            // 里程费
            mileageFeeResult.setMileageAmount(mileageFee);
        }

        // 获取返程费计价规则对象
        ChargeRuleReturn chargeRuleReturn = chargeRuleReturnService.getOne(null);
        // 判断返程费计价规则对象是否为空
        AssertUtil.isNotNull(chargeRuleReturn, "返程费计价失败, 请稍后重试");

        // 获取免费的基础返程里数
        BigDecimal freeBaseReturnMileage = chargeRuleReturn.getFreeBaseReturnMileage();
        // 免费返程里程数
        mileageFeeResult.setFreeBaseReturnMileage(freeBaseReturnMileage);

        // 判断里程数是否在免费的基础返程里数范围内, 如果不是, 那么超出的里程数按超出免费的基础返程里数每公里价格计价
        if (mileage.compareTo(freeBaseReturnMileage) > 0) {
            // 计算超出免费返程里程数
            BigDecimal exceededReturnMileage = mileage.subtract(freeBaseReturnMileage);
            log.info("exceededReturnMileage超出的返程里程数 {}", exceededReturnMileage);
            mileageFeeResult.setExceedFreeBaseReturnMileage(exceededReturnMileage);

            // 计算超出的返程里程数的费用
            BigDecimal exceededReturnMileageFee = exceededReturnMileage.multiply(chargeRuleReturn.getExceedEveryKmAmount());
            log.info("exceededReturnMileageFee超出的返程里程数的费用 {}", exceededReturnMileageFee);
            // 返程费用
            mileageFeeResult.setReturnAmont(exceededReturnMileageFee);

            // 计算预计费用
            mileageFee = mileageFee.add(exceededReturnMileageFee);
            log.info("mileageFee预计费用 {}", mileageFee);
        }
        // 预计费用
        mileageFeeResult.setExpectsOrderAmount(mileageFee);
        // 超出基础里程每公里费用
        mileageFeeResult.setExceedBaseMileageEveryKmAmount(chargeRuleStart.getExceedEveryKmAmount());
        // 超出免费返程里程, 每公里费用
        mileageFeeResult.setExceedBaseReturnEveryKmAmount(chargeRuleReturn.getExceedEveryKmAmount());

        return JSONResult.success(mileageFeeResult);
    }

    /**
     * 计算等时费用
     * @param waitMinute
     * @return
     */
    @Override
    public JSONResult<WaitFeeResult> calculateWaitFee(Integer waitMinute) {
        AssertUtil.isNotNull(waitMinute, "等待时长获取失败");
        // 查询等时计价规则
        ChargeRuleWait chargeRuleWait = chargeRuleWaitService.getOne(null);
        AssertUtil.isNotNull(chargeRuleWait, "等时计价规则不存在");
        // 创建等时费结果返回对象
        WaitFeeResult waitFeeResult = new WaitFeeResult();
        // 获取基础免费等待时长
        Integer freeBaseWaitingMinute = chargeRuleWait.getFreeBaseWaitingMinute();
        waitFeeResult.setFreeBaseWaitingMinute(freeBaseWaitingMinute);
        // 定义等时费
        BigDecimal waitFee = BigDecimal.ZERO;
        waitFeeResult.setExeceedBaseWaitingMinute(BigDecimal.ZERO);
        // 是否超过免费等待时长
        if (waitMinute.compareTo(freeBaseWaitingMinute) > 0) {
            // 获取超出免费等待时间多少分钟
            int exceedMinute = waitMinute - freeBaseWaitingMinute;
            waitFeeResult.setExeceedBaseWaitingMinute(BigDecimal.valueOf(exceedMinute));
            // 获取超出免费时长每分钟多少钱
            BigDecimal exceedEveryMinuteAmount = chargeRuleWait.getExceedEveryMinuteAmount();
            // 计算等时费
            waitFee = new BigDecimal(exceedMinute).multiply(exceedEveryMinuteAmount);
        }
        waitFeeResult.setExeceedBaseWaitingEveryKmAmount(chargeRuleWait.getExceedEveryMinuteAmount());
        waitFeeResult.setWaitingAmount(waitFee);
        return JSONResult.success(waitFeeResult);
    }


    /**
     * 分账计算
     * @param divideAccountsBo
     * @return
     */
    @Override
    public JSONResult<DivideAccountsResult> calculateSplitAccounts(DivideAccountsBo divideAccountsBo) {
        // 获取分账计价规则
        ProfitsharingRuleBase profitsharingRuleBase = profitsharingRuleBaseService.getOne(null);
        AssertUtil.isNotNull(profitsharingRuleBase, "分账计价不存在");

        // 司机分账比例
        BigDecimal driverRatio = profitsharingRuleBase.getDriverRatio();

        // 如果司机当日有取消订单
        if(divideAccountsBo.getNumberOfCancelledOrders() > 0) {
            // 根据取消订单数获取司机需要扣减的分账比例
            ProfitsharingRuleDeductCancel profitsharingRuleDeductCancel = profitsharingRuleDeductCancelService.getOne(new LambdaQueryWrapper<ProfitsharingRuleDeductCancel>()
                    .le(ProfitsharingRuleDeductCancel::getNumberFrom, divideAccountsBo.getNumberOfCancelledOrders())
                    .ge(ProfitsharingRuleDeductCancel::getNumberTo, divideAccountsBo.getNumberOfCancelledOrders()));

            // 取消订单规则存在才进行比例扣减
            if (profitsharingRuleDeductCancel != null) {
                driverRatio = driverRatio.subtract(profitsharingRuleDeductCancel.getDriverRatioDeduct());
            }
        }

        // 如果司机当日有投诉订单
        if(divideAccountsBo.getNumberOfComplaintOrders() > 0) {
            // 根据投诉订单数获取司机需要扣减的分账比例
            ProfitsharingRuleDeductComplaint profitsharingRuleDeductComplaint = profitsharingRuleDeductComplaintService.getOne(new LambdaQueryWrapper<ProfitsharingRuleDeductComplaint>()
                    .le(ProfitsharingRuleDeductComplaint::getNumberFrom, divideAccountsBo.getNumberOfComplaintOrders())
                    .ge(ProfitsharingRuleDeductComplaint::getNumberTo, divideAccountsBo.getNumberOfComplaintOrders()));

            // 投诉订单规则存在才进行比例扣减
            if (profitsharingRuleDeductComplaint != null) {
                driverRatio = driverRatio.subtract(profitsharingRuleDeductComplaint.getDriverRatioDeduct());
            }
        }

        // 根据司机最终分账比例计算分钟金额
        BigDecimal orderAmount = divideAccountsBo.getOrderAmount().multiply(driverRatio);

        // 分账结果
        DivideAccountsResult divideAccountsResult = new DivideAccountsResult()
                .setDriverIncomeAmount(orderAmount.setScale(2, RoundingMode.HALF_UP)) // 司机分成
                .setDriverRate(driverRatio) // 分成比例
                .setPlatformIncomeAmount(divideAccountsBo.getOrderAmount().subtract(orderAmount)) // 平台分成
                .setPlatformRate(new BigDecimal("1").subtract(driverRatio)); // 分成比例

        return JSONResult.success(divideAccountsResult);
    }
}
